package br.com.intelsys.utils.basics.webbrowser;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.httpclient.Cookie;
import org.apache.log4j.Logger;

public class IWebRequest {
	private Map<String, String> paramGetMap;
	private Map<String, String> paramPostMap;
	private Map<String, List<String>> paramHeaderMap;
	private Map<String, Cookie> cookieMap;
	private final String urlStr;
	private final RequestMethod requestMethod;
	private String requestBody;
	private InputStream requestBodyInputStream;
	private String charSet = "UTF-8";
	private boolean autoFollowLocation = false;
	private boolean gzippedContent = false;

	private static Logger log = Logger.getLogger(IWebRequest.class);

	public enum RequestMethod {
		GET, POST, DELETE
	}

	public IWebRequest(URL url) {
		this.urlStr = url.toString();
		this.requestMethod = RequestMethod.GET;
		prepareMySelf();
	}

	public IWebRequest(String url) {
		this.urlStr = url;
		this.requestMethod = RequestMethod.GET;
		prepareMySelf();
	}

	public IWebRequest(URL url, RequestMethod requestMethod) {
		this.urlStr = url.toString();
		this.requestMethod = requestMethod;
		prepareMySelf();
	}

	public IWebRequest(String url, RequestMethod requestMethod) {
		this.urlStr = url;
		this.requestMethod = requestMethod;
		prepareMySelf();
	}

	public IWebRequest charSet(String charSet) {
		this.charSet = charSet;
		return this;
	}

	public IWebRequest requestBody(InputStream inputStream) {
		requestBodyInputStream=inputStream;
		return this;
	}

	public IWebRequest requestBody(String requestBody) {
		this.requestBody=requestBody;
		return this;
	}

	private void prepareMySelf() {
		cookieMap = new HashMap<String, Cookie>();
		paramPostMap = new HashMap<String, String>();
		paramGetMap = new HashMap<String, String>();
		paramHeaderMap = new HashMap<String, List<String>>();
	}

	public IWebRequest addGetParam(String name, String value) {
		paramGetMap.put(name, value);
		return this;
	}

	public IWebRequest addPostParam(String name, String value) {
		paramPostMap.put(name, value);
		return this;
	}

	public IWebRequest addCookie(String name, String value) {
		Cookie c = new Cookie();
		c.setName(name);
		c.setValue(value);
		addCookie(c);
		return this;
	}

	public IWebRequest addCookie(Cookie cookie) {
		if (cookie != null && cookie.getName() != null) {
			if (cookieMap == null) {
				cookieMap = new HashMap<String, Cookie>();
			}
			cookieMap.put(cookie.getName(), cookie);
		}
		return this;
	}

	public IWebRequest removeCookie(String name) {
		addCookie(name, null);
		return this;
	}

	public URL getURL() throws MalformedURLException {
		return new URL(urlStr + getParamGet());
	}

	Map<String, Cookie> getCookieMap() {
		return cookieMap;
	}

	public RequestMethod getRequestMethod() {
		return requestMethod;
	}

	public String getParamGet() {
		String rawData = extractRawData(paramGetMap, '&', charSet);
		if (rawData == null || rawData.length() == 0) {
			return "";
		}
		return (urlStr.contains("?") ? "&" : "?") + rawData;
	}

	public String getParamPost() {
		return extractRawData(paramPostMap, '&', charSet);
	}

	static String extractRawData(Map<String, String> paramMap, char separator, String charSet) {
		StringBuilder sb = new StringBuilder();
		if (paramMap != null) {
			for (Entry<String, String> entry : paramMap.entrySet()) {
				if (sb.length() > 0) {
					sb.append(separator);
				}
				try {
					sb.append(entry.getKey()).append('=').append(URLEncoder.encode(entry.getValue(), charSet));
				} catch (UnsupportedEncodingException e) {
					log.error(e);
				}
			}
		}
		return sb.toString();
	}

	public IWebRequest enableAutoFollowLocation() {
		autoFollowLocation = true;
		return this;
	}

	String getUrlStr() {
		return urlStr;
	}

	public String getCharSet() {
		return charSet;
	}

	Map<String, List<String>> getParamHeaderMap() {
		return paramHeaderMap;
	}

	public IWebRequest addHeader(String name, String value) {
		List<String> valueList;
		if (paramHeaderMap.containsKey(name)) {
			valueList = paramHeaderMap.get(name);
		} else {
			valueList = new ArrayList<String>();
			paramHeaderMap.put(name, valueList);
		}
		valueList.add(value);
		return this;
	}

	public IWebRequest setHeader(String name, String value) {
		List<String> valueList = new ArrayList<String>();
		valueList.add(value);
		paramHeaderMap.put(name, valueList);
		return this;
	}

	public IWebRequest addDefaultHeaders() {
		setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
		setHeader("Accept-Language", "en-us,en;q=0.5");
		setHeader("Connection", "keep-alive");
		setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.0; rv:15.0) Gecko/20100101 Firefox/15.0.1");
		if (requestMethod.equals(RequestMethod.POST)) {
			setHeader("Content-type", "application/x-www-form-urlencoded");
			// setHeader("Content-Length", "42");
		}
		return this;
	}

	public IWebRequest enabledGzippedContent() {
		setHeader("Accept-Encoding", "gzip, deflate");
		gzippedContent = true;
		return this;
	}

	boolean isAutoFollowLocation() {
		return autoFollowLocation;
	}

	public boolean isGzippedContent() {
		return gzippedContent;
	}

	public String toString() {
		try {
			return "{" + super.toString() + ": " + getURL() + "}";
		} catch (MalformedURLException e) {
			return "{" + super.toString() + ": " + getUrlStr() + "}";
		}
	}

	String getRequestBody() {
		return requestBody;
	}

	InputStream getRequestBodyInputStream() {
		return requestBodyInputStream;
	}

}
